package com.aijk.web.admin.controller.openapi;

import com.aijk.commons.exception.ErrorCodeConst;
import com.aijk.commons.exception.ErrorCodeException;
import com.aijk.web.admin.controller.openapi.entity.ApiResponse;
import com.aijk.web.admin.controller.openapi.error.ErrorCodeConstant;
import com.aijk.web.admin.controller.openapi.error.ErrorMessageConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;

/**
 * <p> 异常增强，以JSON的形式返回给客户端 </p>
 * User: chendw
 * Date: 2016/11/1 16:08
 */
@ControllerAdvice
public class ApiBaseController {

    private final Logger logger = LoggerFactory.getLogger(ApiBaseController.class);

    private static final String ERR_TITLE = "API异常";

    //运行时异常
    @ExceptionHandler(RuntimeException.class)
    @ResponseBody
    public ApiResponse runtimeExceptionHandler(RuntimeException ex) {
        logger.info(ERR_TITLE, ex);
        return new ApiResponse(ErrorCodeConst.OPENAPI_MODULE_SERVE + ErrorCodeConstant.CODE_000000, ErrorMessageConstant.MSG_000000000, ex.getMessage());
    }

    //空指针异常
    @ExceptionHandler(NullPointerException.class)
    @ResponseBody
    public ApiResponse nullPointerExceptionHandler(NullPointerException ex) {
        logger.info(ERR_TITLE, ex);
        return new ApiResponse(ErrorCodeConst.OPENAPI_MODULE_SERVE + ErrorCodeConstant.CODE_000002, ErrorMessageConstant.MSG_000000002, ex.getMessage());
    }

    //类型转换异常
    @ExceptionHandler(ClassCastException.class)
    @ResponseBody
    public ApiResponse classCastExceptionHandler(ClassCastException ex) {
        logger.info(ERR_TITLE, ex);
        return new ApiResponse(ErrorCodeConst.OPENAPI_MODULE_SERVE + ErrorCodeConstant.CODE_000003, ErrorMessageConstant.MSG_000000003, ex.getMessage());
    }

    //IO异常
    @ExceptionHandler(IOException.class)
    @ResponseBody
    public ApiResponse iOExceptionHandler(IOException ex) {
        logger.info(ERR_TITLE, ex);
        return new ApiResponse(ErrorCodeConst.OPENAPI_MODULE_SERVE + ErrorCodeConstant.CODE_000004, ErrorMessageConstant.MSG_000000004, ex.getMessage());
    }

    //未知方法异常
    @ExceptionHandler(NoSuchMethodException.class)
    @ResponseBody
    public ApiResponse noSuchMethodExceptionHandler(NoSuchMethodException ex) {
        logger.info(ERR_TITLE, ex);
        return new ApiResponse(ErrorCodeConst.OPENAPI_MODULE_SERVE + ErrorCodeConstant.CODE_000005, ErrorMessageConstant.MSG_000000005, ex.getMessage());
    }

    //数组越界异常
    @ExceptionHandler(IndexOutOfBoundsException.class)
    @ResponseBody
    public ApiResponse indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException ex) {
        logger.info(ERR_TITLE, ex);
        return new ApiResponse(ErrorCodeConst.OPENAPI_MODULE_SERVE + ErrorCodeConstant.CODE_000006, ErrorMessageConstant.MSG_000000006, ex.getMessage());
    }

    //400错误
    @ExceptionHandler({HttpMessageNotReadableException.class})
    @ResponseBody
    public ApiResponse requestNotReadable(HttpMessageNotReadableException ex) {
        logger.info(ERR_TITLE, ex);
        return new ApiResponse(ErrorCodeConst.OPENAPI_MODULE_SERVE + ErrorCodeConstant.CODE_000007, ErrorMessageConstant.MSG_000000007, ex.getMessage());
    }

    //400错误
    @ExceptionHandler({TypeMismatchException.class})
    @ResponseBody
    public ApiResponse requestTypeMismatch(TypeMismatchException ex) {
        logger.info(ERR_TITLE, ex);
        return new ApiResponse(ErrorCodeConst.OPENAPI_MODULE_SERVE + ErrorCodeConstant.CODE_000008, ErrorMessageConstant.MSG_000000008, ex.getMessage());
    }

    //400错误
    @ExceptionHandler({MissingServletRequestParameterException.class})
    @ResponseBody
    public ApiResponse requestMissingServletRequest(MissingServletRequestParameterException ex) {
        logger.info(ERR_TITLE, ex);
        return new ApiResponse(ErrorCodeConst.OPENAPI_MODULE_SERVE + ErrorCodeConstant.CODE_000001, String.format("请求参数[%s]不存在", ex.getParameterName()), ex.getMessage());
    }

    //405错误
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    @ResponseBody
    public ApiResponse request405(HttpRequestMethodNotSupportedException ex) {
        logger.info(ERR_TITLE, ex);
        return new ApiResponse(ErrorCodeConst.OPENAPI_MODULE_SERVE + ErrorCodeConstant.CODE_000010, String.format("不支持[%s]的方式", ex.getMethod()), ex.getMessage());
    }

    //406错误
    @ExceptionHandler({HttpMediaTypeNotAcceptableException.class})
    @ResponseBody
    public ApiResponse request406(HttpMediaTypeNotAcceptableException ex) {
        logger.info(ERR_TITLE, ex);
        return new ApiResponse(ErrorCodeConst.OPENAPI_MODULE_SERVE + ErrorCodeConstant.CODE_000011, "不支持的Media Type", ex.getMessage());
    }

    //500错误
    @ExceptionHandler({ConversionNotSupportedException.class, HttpMessageNotWritableException.class})
    @ResponseBody
    public ApiResponse server500(RuntimeException ex) {
        logger.info(ERR_TITLE, ex);
        return new ApiResponse(ErrorCodeConst.OPENAPI_MODULE_SERVE + ErrorCodeConstant.CODE_000012, "内部错误", ex.getMessage());
    }

    //500错误
    @ExceptionHandler({ErrorCodeException.class})
    @ResponseBody
    public ApiResponse systemError(ErrorCodeException ex) {
        logger.info(ERR_TITLE, ex);
        return new ApiResponse(ex.getCode(), ex.getMessage());
    }

    //400错误
    @ExceptionHandler({BindException.class})
    @ResponseBody
    public ApiResponse validationError(BindException ex) {
        logger.info(ERR_TITLE, ex);
        String errMsg = "";

        for (ObjectError err : ex.getAllErrors()) {
            if (err instanceof FieldError) {
                FieldError fieldError = (FieldError) err;
                errMsg += String.format("[%s]%s ,", fieldError.getField(), err.getDefaultMessage());
            } else {
                errMsg += String.format("[%s]%s ,", err.getObjectName(), err.getDefaultMessage());
            }

        }
        return new ApiResponse(ErrorCodeConst.OPENAPI_MODULE_SERVE + ErrorCodeConstant.CODE_000001, "参数校验失败", ex.getMessage());
    }

    //未知异常
    @ExceptionHandler({Exception.class})
    @ResponseBody
    public ApiResponse exception(BindException ex) {
        logger.info(ERR_TITLE, ex);
        return new ApiResponse(ErrorCodeConst.OPENAPI_MODULE_SERVE + ErrorCodeConstant.CODE_000001, "系统异常", ex.getMessage());
    }
}
